import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import jdk.internal.vm.Continuation;
import jdk.internal.vm.ContinuationScope;

// java --enable-preview --add-opens java.base/jdk.internal.vm=ALL-UNNAMED Prime2
public class Prime2 {
	static final ContinuationScope cs = new ContinuationScope("");
	static final ArrayList<Continuation> readyStack = new ArrayList<>(10000);

	static void loop() {
		for (int n; (n = readyStack.size()) > 0; )
			readyStack.remove(n - 1).run();
	}

	static void resume(Continuation c) {
		readyStack.add(c);
	}

	static void go(Runnable r) {
		new Continuation(cs, r).run();
	}

	static void pause(Deque<Continuation> queue) {
		queue.addLast(Continuation.getCurrentContinuation(cs));
		Continuation.yield(cs);
	}

	static class IntChan {
		private final ArrayDeque<Continuation> waitQueue = new ArrayDeque<>();
		private int value;
		private boolean hasValue;

		void put(int v) {
			if (hasValue)
				pause(waitQueue);
			value = v;
			hasValue = true;
			var c = waitQueue.pollFirst();
			if (c != null)
				resume(c);
		}

		int get() {
			if (!hasValue)
				pause(waitQueue);
			hasValue = false;
			var c = waitQueue.pollFirst();
			if (c != null)
				resume(c);
			return value;
		}
	}

	static void generate(IntChan ch) {
		//noinspection InfiniteLoopStatement
		for (int i = 2; ; i++)
			ch.put(i);
	}

	static void filter(IntChan in, IntChan out, int prime) {
		//noinspection InfiniteLoopStatement
		for (; ; ) {
			var i = in.get();
			if (i % prime != 0)
				out.put(i);
		}
	}

	public static void main(String[] args) {
		var count = args.length > 0 ? Integer.parseInt(args[0]) : 10000;
		var ch = new IntChan();
		go(() -> generate(ch));
		go(() -> {
			var ch0 = ch;
			for (int i = 0; ; ) {
				var prime = ch0.get();
				if (++i == count) {
					System.out.println(prime);
					System.exit(0);
				}
				var ch1 = ch0;
				var ch2 = new IntChan();
				go(() -> filter(ch1, ch2, prime));
				ch0 = ch2;
			}
		});
		loop();
	}
}
